<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
	<button>点我</button>
</body>
<script>
	// 常见的回调函数?
	// 		- DOM事件函数
	// document.querySelector("button").onclick = function(){
	// 	console.log("执行啦")
	// }
	// 		- 定时器函数
	// {
	// 	setTimeout(()=>{
	// 		console.log("执行啦")
	// 	},1000)
	// 	function fn(){
	// 		console.log("执行啦2")
	// 	}
	// 	setTimeout(fn,2000)
	// }
	// 		- `ajax`回调函数
	// const xhr = new XMLHttpRequest();
	// xhr.open("get","./study.js");
	// xhr.send();
	// xhr.onload = function(){
	// 	console.log("执行啦",xhr.response)
	// }
	// 		- 生命周期回调函数
	
	
	
	
	{
		// 	### 立即调用函数（`IIFE`）
		//
		// - 理解
		// - 全称: Immediately-Invoked Function Expression 立即调用函数表达式
		//
		// 	- 别名: 匿名函数自调用
		//
		// 	- 作用
		// 	- 隐藏内部实现
		// 	- 不污染外部命名空间
		
		// let a = 1;
		//
		// (function(window){
		// 	console.log("fn");
		// 	window.a = 100;
		// })(window)
		// console.log(a);
	}
	{
		// 	#### this是什么？
		//    - 一个关键字, 一个内置的引用变量(不需要自定义）
		// 		console.log(this);// window
		// - 在函数中都可以直接使用this
		// function fn(){
		// 	console.log(this);// window
		// }
		// fn();
		
		// - this代表调用函数的当前对象
		// const obj = {
		// 	fn(){
		// 		console.log(this === obj,this);
		// 	}
		// }
		// obj.fn();
		// const fn = obj.fn;
		// fn();
		
		// * 在定义函数时, this还没有确定, 只有在执行时才动态确定(绑定)。（函数当中的this是由执行时的环境决定的）
		
		// window.userName = "window->userName"
		// const obj = {
		// 	userName:"obj->userName",
		// 	fn(a,b){
		// 		console.log(this.userName,a,b);
		// 	}
		// }
		// obj.fn();// obj->userName
		// const fn = obj.fn;
		// fn();// window->userName
		// const obj2 = {
		// 	userName:"obj2->userName"
		// }
		// obj.fn.call(obj2,1,2);// obj2->userName
		// obj.fn.apply(obj2,[3,4]);// obj2->userName
		// obj.fn.bind(obj2,5,6)();// obj2->userName
	}
	{
		// * **默认绑定** ：常用的函数调用类型：独立函数调用
		// * 可以把这个规则看作是无法应用其他规则的时候默认的规则，基本指向的是window
		// function fn(){
		// 	console.log(this)// window
		// }
		// fn();
		//
		// document.querySelector("button").onclick = function(){
		// 	let arr = [1,2,3,4];
		// 	arr.forEach(function(){
		// 		console.log(this);// window
		// 	})
		// }
		//
		
		
		// * **隐式绑定** ：如果函数调用时，前面存在调用它的对象，那么this就会隐式绑定到这个对象上
		// * 当函数引用有上下文对象的时候（obj），隐式绑定规则会把函数中的this绑定到这个上下文对象上
		// const obj = {
		// 	fn(){
		// 		console.log(this);// obj
		// 	}
		// }
		// obj.fn();
		
		// * 隐式绑定可能会出现隐式丢失的问题 ：被隐式绑定的函数，会丢失了绑定对象
		// const obj = {
		// 	fn(){
		// 		console.log(this===obj);
		// 	}
		// }
		// const fn = obj.fn;
		// fn(0)
		
		// * **显式绑定**： 指我们通过call、apply以及bind方法改变this的行为，相比隐式绑定，我们能清楚的感知 this 指向变化过程。
		
		{
			// const obj = {
			// 	str:"obj->str"
			// }
			// document.querySelector("button").onclick = function(){
			// 	console.log(this);
			// }.bind(obj);
			//
			// const obj2 = {
			// 	fn(){
			// 		console.log(this)
			// 	}
			// }
			// obj2.fn();
			// obj2.fn.call(obj);
		}
		// * **`new`绑定**：构造函数只是一些使用new操作符被调用的函数,使用new调用函数的时候，会构造一新的对象，这个时候 就把新的对象绑定给了函数的this上
		function Box(){
			this.a = 1;
			this.b = 2;
			console.log(this);
		}
		new Box();
	
	}
</script>
</html>